<?php

//-----------------------------
// DBQueryi Enhanced Class with Debug

class DBQueryi extends mysqli {

	function __construct($default='eds1', $host=null, $user=null, $password=null, $db=null, $port=null) {
		global $service;
		if(!empty($default) && is_null($host))
			$this->host = $service['hosts'][$default];
		else
			$this->host = $host;
		
		if(!empty($default) && is_null($db))
			$this->db = $service['dbs'][$default];
		else
			$this->db = $db;

		if(is_null($user) || empty($user))
			$this->user = $service['user'];
		else
			$this->user = $user;

		if(is_null($password) || empty($password))
			$this->password = $service['password'];
		else
			$this->password = $password;
			
		if(is_null($port) || empty($port))
			$this->port = 3306;
		else
			$this->port= $port;
		
		if(parent::__construct($this->host, $this->user, $this->password, $this->db, $this->port) === false) {
			exit;
		}

		//$this->autocommit(FALSE);
		// default setting
		mysqli_report( MYSQLI_REPORT_ERROR );
		$this->query( "SET CHARACTER SET utf8" );
		$this->query( "SET SESSION collation_connection = 'utf8_general_ci'" );

		return true;
	}

	function escapeSearchString($string) {
		return str_replace('_', '\_', str_replace('%', '\%', $this->escape_string($string)));
	}
	
	function e($string){
		return mysqli::real_escape_string($string);	
	}
	
	/*@static@*/
	function queryExistence($query) {
		if ($result = $this->query($query)) {
			if ($result->num_rows > 0) {
				$result->free();
				return true;
			}
			$result->free();
		}
		return false;
	}
	
	/*@static@*/
	function queryCount($query) {
		$count = 0;
		if ($result = $this->query($query)) {
			$count = $result->num_rows;
			$result->free();
		}
		return $count;
	}

	/*@static@*/
	function queryCell($query, $field = 0, $useCache=true) {
		$type = MYSQLI_BOTH;
		if (is_numeric($field)) {
			$type = MYSQLI_NUM;
		} else {
			$type = MYSQLI_ASSOC;
		}

		if( $useCache ) {
			$result = $this->queryAllWithCache($query, $type);
		} else {
			$result = $this->queryAll($query, $type);
		}
		if( $result == null ) {
			return null;
		}
		return $result[0][$field];
	}

	/*@static@*/
	function queryRow($query, $type = MYSQLI_BOTH, $useCache=true) {
		if( $useCache ) {
			$result = $this->queryAllWithCache($query, $type, 1);
		} else {
			$result = $this->queryAll($query, $type, 1);
		}
		if( $result == null ) {
			return null;
		}
		return $result[0];
	}

	/*@static@*/
	function queryColumn($query, $useCache=true) {
		global $cachedResulti;
		$cacheKey = "{$this->host}_{$this->db}_{$query}_queryColumn";
		if( $useCache && isset( $cachedResulti[$cacheKey] ) ) {
			if( function_exists( '__tcSqlLogBegini' ) ) {
				__tcSqlLogBegini($this, $query);
				__tcSqlLogEndi($this, null,1);
			}
			$cachedResulti[$cacheKey][0]++;
			return $cachedResulti[$cacheKey][1];
		}

		$column = null;
		if ($result = $this->query($query)) {
			$column = array();
			while ($row = $result->fetch_row())
				array_push($column, $row[0]);
			$result->free();
		}

		if( $useCache ) {
			$cachedResulti[$cacheKey] = array( 1, $column );
		}
		return $column;
	}

	/*@static@*/
	public function queryAll($query, $type = MYSQLI_BOTH, $count = -1) {
		$all = array();
		if ($result = $this->query($query)) {
			while ( ($count-- !=0) && $row = $result->fetch_array($type))
				array_push($all, $row);

			$result->free();
			return $all;
		}
		return null;
	}

	/*@static@*/
	function queryAllWithCache($query, $type = MYSQLI_BOTH, $count = -1) {
		global $cachedResulti;
		$cacheKey = "{$this->host}_{$this->db}_{$query}_{$type}_{$count}";
		if( isset( $cachedResulti[$cacheKey] ) ) {
			if( function_exists( '__tcSqlLogBegini' ) ) {
				__tcSqlLogBegini($this, $query);
				__tcSqlLogEndi($this, null, 1);
			}
			$cachedResulti[$cacheKey][0]++;
			return $cachedResulti[$cacheKey][1];
		}
		$all = $this->queryAll($query, $type, $count);
		$cachedResulti[$cacheKey] = array(1, $all);
		return $all;
	}

	/*@static@*/
	function execute($query) {
		return $this->query($query) ? true : false;
	}

	public function query($query) {
		if( function_exists( '__tcSqlLogBegini' ) ) {
			__tcSqlLogBegini($this, $query);
			$result = @parent::query($query);
			__tcSqlLogEndi($this, $result, 0);
		} else {
			$result = @parent::query($query);
		}

		if( stristr($query, 'update ') ||
			stristr($query, 'insert ') ||
			stristr($query, 'update ') ||
			stristr($query, 'replace ') ) {
			DBQueryi::clearCache();
		}
		return $result;
	}

	public function clearCache() {
		global $cachedResulti;
		$cachedResulti = array();
		if( function_exists( '__tcSqlLogBegin' ) ) {
			__tcSqlLogBegin($this, "Cache cleared" );
			__tcSqlLogEnd($this, null, 2 );
		}
	}

	public function cacheLoad() {
		global $fileCachedResulti;
	}

	public function cacheSave() {
		global $fileCachedResulti;
	}
	
	public function error(){
		return mysqli_error($this);	
	}
	
	public static function showPretty($all){
		if(!count($all))
			return 'no data';
		$str = "<table class=\"debug_table\">";
		$first = false;
		$str .= "<tr>";
		foreach($all[0] as $key => $rows) {
			if(!(is_numeric($key)))
				$str .= "<th>$key</th>";
		}
		$str .= "<tr>";
		foreach($all as $rows) {
			$str .="<tr>";
			foreach($rows as $key => $field) {				
				if((is_numeric($key))) {
					continue;
				}
				$str .= "<td>$field</td>";
				$first = true;
			}
			$str .="</tr>";
			
		}
		return $str."</table>";
	}
}
/*
class Timer {
	private $start, $stop = 0;

	public function __construct() {
		$this->start();
	}

	public function start() {
		$this->start = $this->getMicroTime();
	}

	public function pause() {
		$this->stop = $this->getMicroTime();
	}

	public function resume() {
		$this->start += $this->getMicroTime() - $this->stop;
		$this->stop = 0;
	}

	public function fetch($decimalPlaces = 3) {
		return round(($this->getMicrotime() - $this->start), $decimalPlaces);
	}

	public function getMicroTime() {
		list($usec, $sec) = explode(' ', microtime());
		return (float)$usec + (float)$sec;
	}
}

class Paging {
	public $currentPage, $pageLower, $pageUpper;
	private $limitMaxPage=100, $navigationPages, $rowsPerPage, $totalRows, $totalPages, $format;

	public function __construct($rowsPerPage=20, $navigationPages=9) {
		$this->rowsPerPage = $rowsPerPage;
		$this->navigationPages = $navigationPages;
		if(isset($_GET['page']) && is_numeric($_GET['page']) && $_GET['page'] > 0)
			$this->currentPage = $_GET['page'];
		else if(preg_match('@^/(\d+)@', $_SERVER['SCRIPT_NAME'], $result) && $result[1] > 0)
			$this->currentPage = $result[1];
		else
			$this->currentPage = 1;
	}

	public function setTotalCount($n) {
		$this->totalRows = $n;
	}

	public function setLink($format) {
		$this->format = $format;
	}

	public function getLink($page) {
		return str_replace('%d', $page, $this->format);
	}

	public function calculate() {
		$this->totalPages = min($this->limitMaxPage, intval(ceil($this->totalRows / $this->rowsPerPage)));
		if($this->currentPage > $this->totalPages)
			$this->currentPage = $this->totalPages;
		$this->pageLower = $this->currentPage - floor($this->navigationPages / 2);
		$this->pageUpper = $this->currentPage + floor($this->navigationPages / 2);
		if($this->pageLower < 1) {
			$this->pageUpper -= $this->pageLower - 1;
			$this->pageLower -= $this->pageLower - 1;
		}
		if($this->pageUpper > $this->totalPages) {
			$this->pageLower -= $this->pageUpper - $this->totalPages;
			$this->pageUpper = $this->totalPages;
		}
		$this->pageLower = max($this->pageLower, 1);
		$this->rowsOffset = max(($this->currentPage - 1) * $this->rowsPerPage, 0);
	}

	public function getLimitString() {
		return "{$this->rowsOffset}, {$this->rowsPerPage}";
	}
}

class PageCache {
	protected $lifetime, $fp, $locked, $filename;

	public function __construct($filename, $ignoreLanguage=false) {
		global $client;
		$this->filename = ($ignoreLanguage ? '' : "{$client['language']}.").$filename;
	}

	public function start($lifetime=300, $forceRefresh=false) {
		global $service;
		$forceRefresh = $forceRefresh || !$service['enableCaching'];
		$this->lifetime = $lifetime;
		if(!$forceRefresh && $this->isCacheValid() && $this->sendHeaders() && readfile(ROOT."/cache/{$this->filename}")) {
			exit;
		}
		if($this->fp = fopen(ROOT."/cache/{$this->filename}.tmp", 'w')) {
			if(($this->locked = flock($this->fp, LOCK_EX + LOCK_NB, $wouldblock)) && $wouldblock == 0)
				ob_start();
			else if($this->sendHeaders() && @readfile(ROOT."/cache/{$this->filename}"))
				exit;
			else {
			   @header('HTTP/1.1 503 Service Unavailable');
			   exit;
			}
		}
	}

	public function finish($writeTimestamp=true) {
		if($this->fp && $this->locked) {
			fwrite($this->fp, ob_get_contents());
			if($writeTimestamp)
				fwrite($this->fp, CRLF.'<!-- cached on '.date('r').' -->');
			fclose($this->fp);
			copy(ROOT."/cache/{$this->filename}.tmp", ROOT."/cache/{$this->filename}");
			if(!headers_sent()) {
				header('ETag: "'.md5(filemtime(ROOT."/cache/{$this->filename}")).'"');
				header('Last-Modified: '.gmdate('D, j M Y H:i:s T', filemtime(ROOT."/cache/{$this->filename}")));
			}
			ob_end_flush();
		}
	}

	protected function unlock() {
		@flock($this->fp, LOCK_UN);
		@fclose($this->fp);
		$this->fp = $this->locked = false;
	}

	protected function isCacheValid() {
		clearstatcache();
		return (file_exists(ROOT."/cache/{$this->filename}") && ((time() - filemtime(ROOT."/cache/{$this->filename}")) < $this->lifetime));
	}

	protected function sendHeaders() {
		if(!headers_sent() && ($filetime = @filemtime(ROOT."/cache/{$this->filename}"))) {
			$etag = '"'.md5($filetime).'"';
			$modified = gmdate('D, j M Y H:i:s T', $filetime);
			header('ETag: '.$etag);
			if(@$_SERVER['HTTP_IF_MODIFIED_SINCE'] == $modified && @$_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
				header('HTTP/1.1 304 Not Modified');
				exit;
			}
			header('Expires: '.gmdate('D, j M Y H:i:s T', time() + $this->lifetime));
			header('Last-Modified: '.$modified);
		}
		return true;
	}

	public function expireCache($filename, $ignoreLanguage=false) {
		global $client;
		$filename = ($ignoreLanguage ? '' : "{$client['language']}.").$filename;
		return @unlink(ROOT."/cache/$filename") && @unlink(ROOT."/cache/$filename.tmp");
	}
}

class PartialPageCache extends PageCache {
	public function start($lifetime=300, $forceRefresh=false) {
		global $service;
		$forceRefresh = $forceRefresh || !$service['enableCaching'];
		$this->lifetime = $lifetime;
		if(!$forceRefresh && $this->isCacheValid() && @readfile(ROOT."/cache/{$this->filename}"))
			return true;
		if($this->fp = fopen(ROOT."/cache/{$this->filename}.tmp", 'w')) {
			if(($this->locked = flock($this->fp, LOCK_EX + LOCK_NB, $wouldblock)) && $wouldblock == 0) {
				flush();
				ob_start();
			}
			else {
				// 다른 프로세스가 캐시 파일을 생성중일때 readfile이 실패해도 true를 리턴하므로 화면에는 내용이 표시되지 않는다
				// (캐시 생성되는 동안 오류 허용)
				@readfile(ROOT."/cache/{$this->filename}");
				$this->unlock();
				return true;
			}
		}
		return false;
	}

	public function finish($writeTimestamp=true) {
		if($this->fp && $this->locked) {
			fwrite($this->fp, ob_get_contents());
			if($writeTimestamp)
				fwrite($this->fp, CRLF.'<!-- cached on '.date('r').' -->');
			fclose($this->fp);
			@copy(ROOT."/cache/{$this->filename}.tmp", ROOT."/cache/{$this->filename}");
			@ob_end_flush();
		}
	}

	public function printCachedWhenError($isError) {
		if($isError) {
			$this->unlock();
			$buffer = @ob_get_contents();
			@ob_end_clean();
			if(@readfile(ROOT."/cache/{$this->filename}"))
				return true;
			else {
				echo $buffer;
				return false;
			}
		}
		else
			return false;
	}
}

class LockManager {
	private $path, $fp;

	public function __construct($name) {
		clearstatcache();
		$this->path = ROOT."/log/lock/$name";
		if(($this->fp = fopen($this->path, 'w')) && flock($this->fp, LOCK_EX + LOCK_NB, $wouldblock) && $wouldblock == 0)
			return true;
		exit;
	}

	public function __destruct() {
		flock($this->fp, LOCK_UN);
		fclose($this->fp);
	}

	public function write($message) {
		return file_put_contents("{$this->path}.log", $message);
	}

	public function read() {
		return @file_get_contents("{$this->path}.log");
	}
}*/

class Cipher {
    private $securekey, $iv;
    function __construct($textkey) {
        $this->securekey = hash('sha256',$textkey,TRUE);
        $this->iv = mcrypt_create_iv(32);
    }
    function encrypt($input) {
        return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->securekey, $input, MCRYPT_MODE_ECB, $this->iv));
    }
    function decrypt($input) {
        return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $this->securekey, base64_decode($input), MCRYPT_MODE_ECB, $this->iv));
    }
}

?>